package com.iscas.imchat.sso;

import com.iscas.imchat.utils.Util;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

/**
 * Author: zhd
 * Data: 2022/6/1
 */
public class SingleSignOnServer {

    private int GenPort;
    private int AuthPort;

    private final TokenGenerateService tokenGenerator;
    private final TokenAuthenticateService tokenAuthenticator;

    public SingleSignOnServer(int GenServicePort, int AuthServicePort) {
        this.GenPort = GenServicePort;
        this.AuthPort = AuthServicePort;

        tokenGenerator = new TokenGenerateService(this.GenPort);
        tokenAuthenticator = new TokenAuthenticateService(this.AuthPort);
    }

    public void run_all(){
        try {
            this.tokenGenerator.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("Auth Service Interrupted Exception!");
        }
        try {
            this.tokenAuthenticator.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("Auth Service Interrupted Exception!");
        }

    }

    public static void main(String[] args) throws InterruptedException {
        new SingleSignOnServer(7777,8888).run_all();
    }
}

class TokenGenerateService{

    private int port;

    TokenGenerateService(int port){this.port=port;}

    public void start() throws InterruptedException {
        // token服务器代理
        Util accountUtil=new Util("postgres","password",
                "127.0.0.1","account","5432");
        Util tokenUtil=new Util("postgres","password",
                "127.0.0.1","token","5432");

        // 1.bossGroup 用于接收连接，workerGroup 用于具体的处理
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            //2.创建服务端启动引导/辅助类：ServerBootstrap
            ServerBootstrap b = new ServerBootstrap();
            //3.给引导类配置两大线程组,确定了线程模型
            b.group(bossGroup, workerGroup)
                    // (非必备)打印日志
                    .handler(new LoggingHandler(LogLevel.INFO))
                    // 4.指定 IO 模型
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) {
                            ChannelPipeline p = ch.pipeline();
                            //5.可以自定义客户端消息的业务处理逻辑
                            p.addLast("encoder",new StringEncoder());
                            p.addLast("decoder",new StringDecoder());
                            p.addLast(new TokenGenerateHandler(accountUtil,tokenUtil));
                        }
                    });
            // 6.绑定端口,调用 sync 方法阻塞知道绑定完成
            ChannelFuture f = b.bind(port).sync();
            // 7.阻塞等待直到服务器Channel关闭(closeFuture()方法获取Channel 的CloseFuture对象,然后调用sync()方法)
            f.channel().closeFuture().sync();
        } finally {
            //8.优雅关闭相关线程组资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
            //关流
            tokenUtil.close();
        }
    }
}

class TokenAuthenticateService{

    private int port;

    TokenAuthenticateService(int port){this.port=port;}

    public void start() throws InterruptedException {
        // 用户状态服务器代理
        Util tokenUtil=new Util("postgres","password",
                "127.0.0.1","token","5432");

        // 1.bossGroup 用于接收连接，workerGroup 用于具体的处理
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            //2.创建服务端启动引导/辅助类：ServerBootstrap
            ServerBootstrap b = new ServerBootstrap();
            //3.给引导类配置两大线程组,确定了线程模型
            b.group(bossGroup, workerGroup)
                    // (非必备)打印日志
                    .handler(new LoggingHandler(LogLevel.INFO))
                    // 4.指定 IO 模型
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) {
                            ChannelPipeline p = ch.pipeline();
                            //5.可以自定义客户端消息的业务处理逻辑
                            p.addLast("encoder",new StringEncoder());
                            p.addLast("decoder",new StringDecoder());
                            p.addLast(new TokenAuthenticateHandler(tokenUtil));
                        }
                    });
            // 6.绑定端口,调用 sync 方法阻塞知道绑定完成
            ChannelFuture f = b.bind(port).sync();
            // 7.阻塞等待直到服务器Channel关闭(closeFuture()方法获取Channel 的CloseFuture对象,然后调用sync()方法)
            f.channel().closeFuture().sync();
        } finally {
            //8.优雅关闭相关线程组资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
            //关流
            tokenUtil.close();
        }
    }
}
